
import requests
import re
import json
from libs.conn import log_error

# 转换为数字，可指定进制
def try_convert_to_int(value, base=10):
    """尝试将值转换为 int，如果失败则返回 None"""
    value1 = value
    if value1 is None:
        return None
    if value1 == '':
        return None
    if '.' in value:
        # 去掉小数部分
        value1 = value1.split('.')[0]
    try:
        return int(value1, base)
    except Exception as e:
        log_error(f'值 {value} 转换为int类型失败: {str(e)}')
        return None

def get_status(ip, port = 80):
    url = f'http://{ip}:{port}/gui/status_main.cgi'
    # 使用字典简化表单数据
    data = {
        "sim": "false",
        "cellinfo": "true",
        "cellinfo2": "false",
        "lan": "false",
        "basic": "false",
        "wan": "false",
        "static_route": "false",
        "policy_route": "false",
        "ipv6_route": "false",
        "ActionType": "Refresh",
        "system": "true",
        "Ajax": "true",
        "modem_ip_info": "false",
        "TokenKey": "",
        "modem2": "false",
        "T": "",
        "modem": "0", # 兼容写法
        "wlan": "false",
        "wlan_ac": "false"
    }

    try:
        # 直接使用 files 参数处理 multipart/form-data
        response = requests.post(
            url,
            files=[(k, (None, v)) for k, v in data.items()],
            headers={
                "Accept": "application/json, text/javascript, */*; q=0.01",
                "X-Requested-With": "XMLHttpRequest"
            },
            cookies={
                "username": "admin",
                "global_url": "status_main.cgi"
            }
        )
        if response.status_code == 200:
            data = response.json()
            return handle_status(data)
        else:
            log_error(f'获取模组信息失败, url为：{url}，响应状态为：{response.status_code}')
            return None
    except Exception as e:
        log_error(f'获取模组信息失败: {str(e)}，url：{url}')
        return None

def network_generation(tech: str) -> int:
    """
    将基站技术标识转换为数字代际（2G/3G/4G/5G）
    支持混合输入（如"5G NSA"），按最高代际返回
    
    参数:
        tech (str): 基站技术标识字符串（不区分大小写）
        
    返回:
        int: 对应的数字代际（未知标识返回0）
    """
    # 统一转换为大写便于处理
    tech_upper = tech.upper()
    
    # 按代际从高到低检查（5G > 4G > 3G > 2G）
    # 5G 技术标识（优先检查长关键词）
    for keyword in ["NSA", "SA", "NR", "5G"]:
        if keyword in tech_upper:
            return 5
    
    # 4G 技术标识
    for keyword in ["LTE-A", "LTE_PRO", "LTE_A", "LTE", "4G"]:
        if keyword in tech_upper:
            return 4
    
    # 3G 技术标识
    for keyword in ["TD-SCDMA", "CDMA2000", "HSPA", "WCDMA", "UMTS", "3G"]:
        if keyword in tech_upper:
            return 3
    
    # 2G 技术标识
    for keyword in ["EDGE", "GPRS", "GSM", "2G"]:
        if keyword in tech_upper:
            return 2
    
    # 未知技术标识
    return 0

# 适用于版本 V2.0.6_CUIOT
def handle_model_status_1(data, key):
    modem_html = data[key]['modem']
    # 使用正则表达式提取所需值,包括字母、数字、-号
    matches = re.findall(r'<td>([A-Za-z\d-]*)</td>', modem_html)
    print(matches)
    if len(matches) >= 8:
        try:
            return {
                "cell_gen": network_generation(matches[0]),
                "cell_id": try_convert_to_int(matches[1], 16),
                "cell_pci": try_convert_to_int(matches[2]),
                "cell_tac": try_convert_to_int(matches[3]),
                "cell_arfcn": try_convert_to_int(matches[4]),
                "cell_band": try_convert_to_int(matches[5]),
                "cell_rsrp": try_convert_to_int(matches[6]),
                "cell_sinr": try_convert_to_int(matches[7]),
                "cell_rssi": try_convert_to_int(matches[8]),
                "cell_rsrq": try_convert_to_int(matches[9]),
            }
        except Exception as e:
            raise Exception(f'模组信息 {matches} 处理失败。错误信息：{str(e)}')
    else:
        raise Exception(f'modem信息html格式错误, 响应信息为：{data}')

# 适用于版本 H8900_APP_V7.8.0_T1
def handle_model_status_2(data):
    modem_infos = data['modem'][0]['cell_info']
    try:
        for modem_info in modem_infos:
            if modem_info['nettype'] == '':
                continue
            print(modem_info)
            if modem_info:
                return {
                    "cell_gen": network_generation(modem_info['nettype']),
                    "cell_id": try_convert_to_int(modem_info['cellid'], 16),
                    "cell_pci": try_convert_to_int(modem_info['pcid']),
                    "cell_tac": try_convert_to_int(modem_info['tac']),
                    "cell_arfcn": try_convert_to_int(modem_info['arfcn']),
                    "cell_band": try_convert_to_int(modem_info['band']),
                    "cell_rsrp": try_convert_to_int(modem_info['rsrp']),
                    "cell_sinr": try_convert_to_int(modem_info['sinr']),
                    "cell_rssi": try_convert_to_int(modem_info['rssi']),
                    "cell_rsrq": try_convert_to_int(modem_info['rsrq']),
                }
        raise Exception(f'没有找到有效的modem信息，响应信息为：{data}')
    except Exception as e:
        raise Exception(f'模组信息 {modem_infos} 处理失败。错误信息：{str(e)}')

def handle_status(data):
    result = {}
    # 1. 提取网络速度
    # 判断是否有'network_speed_up'和'network_speed_down'键，以及字符串是否为有效数字
    if 'network_speed_up' not in data['system'] or 'network_speed_down' not in data['system']:
        raise Exception(f'无法解析有效网络速度，响应信息为：{data}')
    network_speed_up = try_convert_to_int(data['system']['network_speed_up'])
    network_speed_down = try_convert_to_int(data['system']['network_speed_down'])
    result["network_speed_up"] =  None if network_speed_up is None else network_speed_up * 8 // 1000 # 单位从B/s转为kbps
    result["network_speed_down"] = None if network_speed_down is None else network_speed_down * 8 // 1000 # 单位从B/s转为kbps
    # 2. 提取modem中的信息
    modem_info = None
    # 判断data是否有'cellinfo'键
    if 'cellinfo' in data:
        modem_info = handle_model_status_1(data, 'cellinfo')
    elif 'cellinfo2' in data:
        modem_info = handle_model_status_1(data, 'cellinfo2')
    elif 'modem' in data:
        modem_info = handle_model_status_2(data)
    else:
        raise Exception(f'无法解析有效modem信息，响应信息为：{data}')
    # 将modem_info的键值对添加到result中，同时保留result中已有的键值对
    if modem_info:
        result.update(modem_info)
      
    return result
    # {
    #     "network_speed_up": network_speed_up,
    #     "network_speed_down": network_speed_down,
    #     "cell_gen": gen,  # 表示4G还是5G
    #     "cell_id": cell_id,
    #     "cell_pci": pci,
    #     "cell_tac": tac,
    #     "cell_arfcn": arfcn,
    #     "cell_band": band,
    #     "cell_rsrp": rsrp,
    #     "cell_sinr": sinr,
    #     "cell_rssi": rssi,
    #     "cell_rsrq": rsrq
    # }

# Example usage
if __name__ == '__main__':
    result = get_status('192.168.11.197', 80)
    print(result)